﻿using AutoMapper;
using ProjectManageSystemApi.DbEntity;
using ProjectManageSystemApi.Enums;
using ProjectManageSystemApi.Models;
using ProjectManageSystemApi.Utilities;
using System;
using System.Collections.Generic;

namespace ProjectManageSystemApi.Services.Impl
{
    public class ProjectItemInfoServices : IProjectItemInfoServices
    {
        readonly IMapper _mapper;
        readonly IFreeSql _fsql;
        // readonly IProjectItemPriceRecordServices _priceRecord;
        public ProjectItemInfoServices(IFreeSql fsql, IMapper mapper
            // , IProjectItemPriceRecordServices priceRecord
        )
        {
            _mapper = mapper;
            _fsql = fsql;
            // _priceRecord = priceRecord;
        }

        public bool Insert(ProjectItemInfoDto itemData)
        {
            var data = _mapper.Map<ItemInfo>(itemData);
            data.CreateTime = DateTime.Now.GetMillUtcTimeStamp();
            data.State = (int)ProjectItemInfoStatus.Default;
            return _fsql.Insert(data).IgnoreColumns(x=> new { x.ModifyTime, x.ModifyUser }).ExecuteAffrows() > 0;
        }

        public bool Update(ProjectItemInfoDto itemData, long userId)
        {
            var data = _mapper.Map<ItemInfo>(itemData);
            data.ModifyTime = DateTime.Now.GetMillUtcTimeStamp();
            data.ModifyUser = userId;
            data.State = (int)ProjectItemInfoStatus.Default;
            return _fsql.Update<ItemInfo>().SetSource(data)
                .IgnoreColumns(x => new { x.CreateTime, x.CreateUser, x.ProjectId, x.State }).ExecuteAffrows() > 0;
        }

        public Models.PageVo<List<ProjectItemInfoDto>> GetByProjectId(Models.PageBo<ProjectItemInfoParams> pageBo)
        {
            var data = _fsql.Select<ItemInfo>()
                .IncludeMany(x => x.ItemImageInfos)
                .Where(x => x.ProjectId == pageBo.Param.ProjectId && x.State == (int)ProjectItemInfoStatus.Default)
                .OrderByDescending(x => x.CreateTime);
            if (!string.IsNullOrWhiteSpace(pageBo.Param.ItemName))
            {
                data = data.Where(x => x.ItemName.Contains(pageBo.Param.ItemName));
            }
            long count = data.Count();
            data = data.Page(pageBo.Page, pageBo.Size);
            return new Models.PageVo<List<ProjectItemInfoDto>>
            {
                Page = pageBo.Page,
                Size = pageBo.Size,
                Total = count,
                Datas = _mapper.Map<List<ProjectItemInfoDto>>(data.ToList())
            };
        }

        public bool Delete(int projectItemId)
        {
            return _fsql.Update<ItemInfo>(projectItemId).Set(x => x.State, (sbyte)ProjectItemInfoStatus.Delete).ExecuteAffrows() > 0;
        }

        public bool HasExistItemName(int projectId, string itemName, int itemId = 0) 
        {
            return _fsql.Select<ItemInfo>().Any(x => x.ProjectId == projectId && x.ItemName == itemName 
                && x.Id != itemId && x.State == (sbyte)ProjectItemInfoStatus.Default);
        }
        
        public bool HasExistItemId(int itemId) 
        {
            return _fsql.Select<ItemInfo>().Any(x => x.Id == itemId && x.State == (sbyte)ProjectItemInfoStatus.Default);
        }

        public ProjectItemDto GetProjectItemInfoByManager(int itemId)
        {
            return _fsql.Select<ItemInfo>().Where(x => x.Id == itemId)
                .ToOne(x => new ProjectItemDto
                {
                    ItemName = x.ItemName,
                    ItemDesc = x.ItemDesc,
                    BudgetAmount = x.BudgetAmount,
                    BudgetDosage = x.BudgetDosage,
                    FactAmount = x.FactAmount,
                    FactDosage = x.FactDosage,
                    Unit = x.Unit,
                    UnCheckCostAmount = _fsql.Select<CostInfo>()
                        .Where(c => c.ItemId == x.Id)
                        .Where(c => c.State == (sbyte)EnumCostApplyInfo.Nomal)
                        .Sum(s => s.CostAmount),
                    CheckCostAmount = _fsql.Select<CostInfo>()
                        .Where(c => c.ItemId == x.Id)
                        .Where(c => c.State == (sbyte)EnumCostApplyInfo.ManagerPassed 
                            || c.State == (sbyte)EnumCostApplyInfo.FinancerPassed)
                        .Sum(s => s.CostAmount)
                });
        }

        public ProjectItemDto GetProjectItemInfoByFinancer(int itemId)
        {
            return _fsql.Select<ItemInfo>().Where(x => x.Id == itemId)
                .ToOne(x => new ProjectItemDto
                {
                    ItemName = x.ItemName,
                    ItemDesc = x.ItemDesc,
                    BudgetAmount = x.BudgetAmount,
                    BudgetDosage = x.BudgetDosage,
                    FactAmount = x.FactAmount,
                    FactDosage = x.FactDosage,
                    Unit = x.Unit,
                    UnCheckCostAmount = _fsql.Select<CostInfo>()
                        .Where(c => c.ItemId == x.Id)
                        .Where(c => c.State == (sbyte)EnumCostApplyInfo.ManagerPassed)
                        .Sum(s => s.CostAmount),
                    CheckCostAmount = _fsql.Select<CostInfo>()
                        .Where(c => c.ItemId == x.Id)
                        .Where(c => c.State == (sbyte)EnumCostApplyInfo.FinancerPassed)
                        .Sum(s => s.CostAmount)
                });
        }
        
        public bool Insert(int projectId, List<ProjectItemData> datas, long userId)
        {
            var data = _mapper.Map<List<ItemInfo>>(datas);
            foreach (var d in data) 
            {
                d.ProjectId = projectId;
                d.CreateTime = DateTime.Now.GetMillUtcTimeStamp();
                d.State = (int)ProjectItemInfoStatus.Default;
                d.CreateUser = userId;
            }
            return _fsql.Insert(data).ExecuteAffrows() >= datas.Count;
        }
        public ItemInfo GetById(int itemId) 
        {
            return _fsql.Select<ItemInfo>().Where(x=>x.Id == itemId).ToOne();
        }
    }
}
